diff options
Diffstat (limited to 'app/api/evaluation/attachments/[id]/route.ts')
| -rw-r--r-- | app/api/evaluation/attachments/[id]/route.ts | 151 |
1 files changed, 151 insertions, 0 deletions
diff --git a/app/api/evaluation/attachments/[id]/route.ts b/app/api/evaluation/attachments/[id]/route.ts new file mode 100644 index 00000000..dfdc0eb9 --- /dev/null +++ b/app/api/evaluation/attachments/[id]/route.ts @@ -0,0 +1,151 @@ +// app/api/evaluation/attachments/[id]/route.ts +import { NextRequest, NextResponse } from "next/server"; +import db from "@/db/db"; +import { reviewerEvaluationAttachments } from "@/db/schema"; +import { eq } from "drizzle-orm"; +import { getServerSession } from "next-auth/next" +import { authOptions } from "@/app/api/auth/[...nextauth]/route" +import { deleteFile } from "@/lib/file-stroage"; + +interface Context { + params: { + id: string; + }; +} + +// 첨부파일 삭제 +export async function DELETE( + request: NextRequest, + { params }: Context +) { + try { + // 인증 확인 + const session = await getServerSession(authOptions); + if (!session?.user?.id) { + return NextResponse.json( + { success: false, error: "인증이 필요합니다." }, + { status: 401 } + ); + } + + const attachmentId = parseInt(params.id); + if (isNaN(attachmentId)) { + return NextResponse.json( + { success: false, error: "유효하지 않은 첨부파일 ID입니다." }, + { status: 400 } + ); + } + + const result = await db.transaction(async (tx) => { + // 1. 첨부파일 정보 조회 + const attachment = await tx + .select({ + id: reviewerEvaluationAttachments.id, + publicPath: reviewerEvaluationAttachments.publicPath, + uploadedBy: reviewerEvaluationAttachments.uploadedBy, + }) + .from(reviewerEvaluationAttachments) + .where(eq(reviewerEvaluationAttachments.id, attachmentId)) + .limit(1); + + if (attachment.length === 0) { + throw new Error("첨부파일을 찾을 수 없습니다."); + } + + // 2. 권한 확인 (업로드한 사용자만 삭제 가능) + if (attachment[0].uploadedBy !== parseInt(session.user.id)) { + throw new Error("삭제 권한이 없습니다."); + } + + // 3. DB에서 첨부파일 정보 삭제 + await tx + .delete(reviewerEvaluationAttachments) + .where(eq(reviewerEvaluationAttachments.id, attachmentId)); + + // 4. 물리적 파일 삭제 + try { + await deleteFile(attachment[0].publicPath); + } catch (fileError) { + console.warn("물리적 파일 삭제 실패:", fileError); + // 파일 삭제 실패는 DB 삭제를 롤백하지 않음 + } + + return true; + }); + + return NextResponse.json({ + success: true, + message: "첨부파일이 삭제되었습니다.", + }); + + } catch (error) { + console.error("첨부파일 삭제 실패:", error); + return NextResponse.json( + { + success: false, + error: error instanceof Error ? error.message : "첨부파일 삭제 중 오류가 발생했습니다.", + }, + { status: 500 } + ); + } +} + +// 특정 첨부파일 정보 조회 +export async function GET( + request: NextRequest, + { params }: Context +) { + try { + const session = await getServerSession(authOptions); + if (!session?.user?.id) { + return NextResponse.json( + { success: false, error: "인증이 필요합니다." }, + { status: 401 } + ); + } + + const attachmentId = parseInt(params.id); + if (isNaN(attachmentId)) { + return NextResponse.json( + { success: false, error: "유효하지 않은 첨부파일 ID입니다." }, + { status: 400 } + ); + } + + const attachment = await db + .select({ + id: reviewerEvaluationAttachments.id, + originalFileName: reviewerEvaluationAttachments.originalFileName, + publicPath: reviewerEvaluationAttachments.publicPath, + fileSize: reviewerEvaluationAttachments.fileSize, + mimeType: reviewerEvaluationAttachments.mimeType, + description: reviewerEvaluationAttachments.description, + createdAt: reviewerEvaluationAttachments.createdAt, + }) + .from(reviewerEvaluationAttachments) + .where(eq(reviewerEvaluationAttachments.id, attachmentId)) + .limit(1); + + if (attachment.length === 0) { + return NextResponse.json( + { success: false, error: "첨부파일을 찾을 수 없습니다." }, + { status: 404 } + ); + } + + return NextResponse.json({ + success: true, + attachment: attachment[0], + }); + + } catch (error) { + console.error("첨부파일 조회 실패:", error); + return NextResponse.json( + { + success: false, + error: "첨부파일 조회 중 오류가 발생했습니다.", + }, + { status: 500 } + ); + } +}
\ No newline at end of file |
